import {Color} from '../color';
import {Plugin} from '../extend';
import {AnyColor} from '../type';
import {mix} from '../manipulate/mix';

declare module '../color' {
    interface Color {
        /**
         * Produces a mixture of two colors through CIE LAB color space and returns a new Color instance.
         */
        mix(color2: AnyColor | Color, ratio?: number): Color;

        /**
         * Generates a tints palette based on original color.
         */
        tints(count?: number): Color[];

        /**
         * Generates a shades palette based on original color.
         */
        shades(count?: number): Color[];

        /**
         * Generates a tones palette based on original color.
         */
        tones(count?: number): Color[];
    }
}

/**
 * A plugin adding a color mixing utilities.
 */
const mixPlugin: Plugin = (ColorClass): void => {
    /**
     * Generate a palette from mixing a source color with another.
     */
    function mixPalette(source: Color, hex: string, count = 5): Color[] {
        const palette = [];
        const step = 1 / (count - 1);
        for (let i = 0; i <= count - 1; i++) {
            palette.push(source.mix(hex, step * i));
        }
        return palette;
    }

    ColorClass.prototype.mix = function(color2, ratio = 0.5) {
        const instance2 = color2 instanceof ColorClass ? color2 : new ColorClass(color2);

        const mixture = mix(this.toRgb(), instance2.toRgb(), ratio);
        return new ColorClass(mixture);
    };

    ColorClass.prototype.tints = function(count) {
        return mixPalette(this, '#fff', count);
    };

    ColorClass.prototype.shades = function(count) {
        return mixPalette(this, '#000', count);
    };

    ColorClass.prototype.tones = function(count) {
        return mixPalette(this, '#808080', count);
    };
};

export default mixPlugin;
